package com.android.demo_20220829.manager;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;

import androidx.appcompat.content.res.AppCompatResources;

import com.mapbox.android.core.permissions.PermissionsManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.geojson.Point;
import com.mapbox.maps.CameraOptions;
import com.mapbox.maps.MapView;
import com.mapbox.maps.MapboxMap;
import com.mapbox.maps.Style;
import com.mapbox.maps.extension.style.expressions.generated.Expression;
import com.mapbox.maps.plugin.LocationPuck2D;
import com.mapbox.maps.plugin.Plugin;
import com.mapbox.maps.plugin.animation.CameraAnimationsPlugin;
import com.mapbox.maps.plugin.animation.MapAnimationOptions;
import com.mapbox.maps.plugin.annotation.AnnotationPlugin;
import com.mapbox.maps.plugin.annotation.AnnotationType;
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager;
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions;
import com.mapbox.maps.plugin.attribution.AttributionPlugin;
import com.mapbox.maps.plugin.compass.CompassPlugin;
import com.mapbox.maps.plugin.gestures.GesturesPlugin;
import com.mapbox.maps.plugin.gestures.OnMoveListener;
import com.mapbox.maps.plugin.locationcomponent.LocationComponentPlugin;
import com.mapbox.maps.plugin.locationcomponent.OnIndicatorPositionChangedListener;
import com.mapbox.maps.plugin.logo.LogoPlugin;
import com.mapbox.maps.plugin.scalebar.ScaleBarPlugin;
import com.mapbox.maps.viewannotation.ViewAnnotationManager;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
 * @author CHENEY
 * @date 2022/3/23
 */
public class MapBoxUtil {
    private static final String TAG = "MapBoxUtil";

    private static final String DEFAULT_MAP_STYLE = Style.MAPBOX_STREETS;   // 地图显示样式
    private static final double DEFAULT_LOCATION_LATITUDE = 32.55;    // 初始地图显示坐标
    private static final double DEFAULT_LOCATION_LONGITUDE = 110.06;
    private static final double DEFAULT_ZOOM_VALUE = 12.0;   // 初始地图缩放大小
    private static final double LOCATE_ZOOM_VALUE = 14.0;   // 定位后地图缩放大小

    private final MapView mMapView;
    private final Context mContext;
    private final MapboxMap mMapboxMap;
    private PointAnnotationManager mPointAnnotationManager; // point类型 注释Manager
    private ViewAnnotationManager mViewAnnotationManager;   // 自定义view 注释Manager
//    private ClusterLayer clusterLayer;
    private final OnStyleLoadFinishListener mOnStyleLoadFinishListener; // 地图加载完毕回调

    // 地图组件
    private AnnotationPlugin mAnnotationPlugin;         // 地图注释组件
    private LocationComponentPlugin mLocationPlugin;    // 位置定位组件
    private GesturesPlugin mGesturesPlugin;     // 手势组件
    private CameraAnimationsPlugin mCameraAnimationsPlugin;     // 相机动画组件

    private boolean isCameraFollowUser = false; // 设置相机是否始终跟随用户

    // 过程状态变量
    private boolean isMapMoving = false;
    private boolean isCameraToUserInit = false; // 首次设置摄像头到用户位置
    private Point mUserLocation;    // 用户位置

    public MapBoxUtil(@NotNull MapView mapView, Context context, boolean isShowUserLocation,
                      OnStyleLoadFinishListener listener) {
        mMapView = mapView;
        mContext = context;
        mMapboxMap = mapView.getMapboxMap();
        mOnStyleLoadFinishListener = listener;
        mapInit(isShowUserLocation);
        pluginInit();
    }

    public interface OnStyleLoadFinishListener {
        void onFinish();
    }

    // 隐藏地图左下角logo
    public MapBoxUtil hideLogo() {
        if (mMapView == null) {
            return this;
        }
//        // 根据官网使用要求，不建议隐藏
//        LogoPlugin logoPlugin =  mMapView.getPlugin(Plugin.MAPBOX_LOGO_PLUGIN_ID);
//        if (logoPlugin != null) {
//            logoPlugin.setEnabled(false);
//        }
        AttributionPlugin attributionPlugin = mMapView.getPlugin(Plugin.MAPBOX_ATTRIBUTION_PLUGIN_ID);
        if (attributionPlugin != null) {
            attributionPlugin.setEnabled(false);
        }
        return this;
    }

    // 隐藏地图左上角比例尺
    public MapBoxUtil hideScaleBar() {
        if (mMapView == null) {
            return this;
        }
        ScaleBarPlugin scaleBarPlugin = mMapView.getPlugin(Plugin.MAPBOX_SCALEBAR_PLUGIN_ID);
        if (scaleBarPlugin != null) {
            scaleBarPlugin.setEnabled(false);
        }
        return this;
    }

    /**
     * 初始化地图指南针
     * (注意：全屏模式下设置指南针会有问题[未解决])
     * @param isEnable 是否显示
     * @param drawable 指南针样式，为空时为MapBox默认样式
     */
    public void initCompassUI(boolean isEnable, @Nullable Drawable drawable,
                                    float marginTop, float marginRight) {
        if (mMapView == null) {
            return;
        }
        CompassPlugin compassPlugin = mMapView.getPlugin(Plugin.MAPBOX_COMPASS_PLUGIN_ID);
        if (compassPlugin == null) {
            return;
        }
        if (!isEnable) {
            compassPlugin.setEnabled(isEnable);
            return;
        }
        if (drawable != null){
            compassPlugin.setImage(drawable);
        }
        compassPlugin.setMarginTop(marginTop);
        compassPlugin.setMarginRight(marginRight);
    }

    // 相机 和 地图初始化
    private void mapInit(boolean isShowUserLocation) {
        mMapboxMap.setCamera(  // 设置地图相机初始位置
                new CameraOptions.Builder()
                        .center(Point.fromLngLat(DEFAULT_LOCATION_LONGITUDE, DEFAULT_LOCATION_LATITUDE))
                        .zoom(DEFAULT_ZOOM_VALUE)
                        .build());
        mMapboxMap.loadStyleUri(   // 加载地图
                DEFAULT_MAP_STYLE, style -> {
//                    if (isShowUserLocation) {
//                        // 获取位置权限
//                        PermissionUtil.verifyPermissions(mContext,
//                                PermissionUtil.PERMISSIONS_USER_LOCATION,
//                                PermissionUtil.REQUEST_CODE_USER_LOCATION);
//                        showUserLocation(true, false);
//                    }
//                    clusterLayer = new ClusterLayer(mContext, mMapboxMap, style);

                    if (mOnStyleLoadFinishListener != null) {
                        mOnStyleLoadFinishListener.onFinish();
                    }
                });
    }

    // 组件初始化
    private void pluginInit() {
        mAnnotationPlugin = mMapView.getPlugin(Plugin.MAPBOX_ANNOTATION_PLUGIN_ID);
        mGesturesPlugin = mMapView.getPlugin(Plugin.MAPBOX_GESTURES_PLUGIN_ID);
        mCameraAnimationsPlugin = mMapView.getPlugin(Plugin.MAPBOX_CAMERA_PLUGIN_ID);
        if (mGesturesPlugin != null) {
            mGesturesPlugin.addOnMoveListener(onMoveListener);
        }
    }

    /**
     * 在地图上显示用户位置
     * @param isPulsingEnabled  是否显示图标脉冲效果
     * @param isCameraFollow    相机始终跟随
     */
    private void showUserLocation(boolean isPulsingEnabled, boolean isCameraFollow) {
        if (mLocationPlugin == null) {  // 初始化
            mLocationPlugin = mMapView.getPlugin(Plugin.MAPBOX_LOCATION_COMPONENT_PLUGIN_ID);
            if (mLocationPlugin == null) {
                return;
            }
        }
        isCameraFollowUser = isCameraFollow;
        // 设置脉冲显示
        if (isPulsingEnabled) {
            mLocationPlugin.updateSettings(locationComponentSettings -> {
                locationComponentSettings.setEnabled(true);
                locationComponentSettings.setPulsingEnabled(true);  // 脉冲效果
                return null;
            });
        }
//        // 设置图标随地图缩放比例变化
//        Expression.InterpolatorBuilder interpolatorBuilder = new Expression.InterpolatorBuilder("interpolate");
//        interpolatorBuilder.linear();
//        interpolatorBuilder.zoom();
//        interpolatorBuilder.stop(expressionBuilder -> {
//            expressionBuilder.literal(0.0);
//            expressionBuilder.literal(1.0);
//            return null;
//        });
//        interpolatorBuilder.stop(expressionBuilder -> {
//            expressionBuilder.literal(20.0);
//            expressionBuilder.literal(1.5);
//            return null;
//        });
//        Log.d(TAG,"[showUserLocation]icon scale rule: " + interpolatorBuilder.build().toJson());
//        // 设置用户位置图标样式
//        mLocationPlugin.setLocationPuck(new LocationPuck2D(null,
//                AppCompatResources.getDrawable(mContext, R.drawable.mapbox_user_icon),
//                AppCompatResources.getDrawable(mContext, R.drawable.mapbox_user_stroke_icon),
//                interpolatorBuilder.build().toJson()));
//        // 添加用户位置监听器
//        mLocationPlugin.addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener);
    }

    /**
     * 将摄像头移动到用户位置
     * @param duration  移动动画耗时 0为无动画
     */
    public void moveCameraToUserPos(int duration) {
        if (mUserLocation == null) {
            return;
        }
        moveCameraTo(mUserLocation, LOCATE_ZOOM_VALUE, duration);
    }

    /**
     * 将摄像头移动到指定位置
     * @param point 目标坐标
     * @param zoom  缩放比例
     * @param duration 滑动总时间 0为无动画
     */
    public void moveCameraTo(Point point, double zoom, int duration) {
        if (mMapView == null) {
            return;
        }
        if (duration != 0 && mCameraAnimationsPlugin != null) {
            mCameraAnimationsPlugin.flyTo(new CameraOptions.Builder()
                            .center(point)
                            .zoom(zoom)
                            .build(),
                    new MapAnimationOptions.Builder().duration(duration).build());
        } else {
            mMapboxMap.setCamera(new CameraOptions.Builder()
                    .center(point)
                    .zoom(zoom)
                    .build());
        }
    }

    /**
     * 在地图中添加Point类型标记
     * @param longitude 添加坐标X
     * @param latitude  添加坐标Y
     */
    public void addPointAnnotationInMap(int drawable, double longitude, double latitude) {
//        if(mAnnotationPlugin == null){
//            return;
//        }
//        if (mPointAnnotationManager == null) {
//            mPointAnnotationManager = (PointAnnotationManager)
//                    mAnnotationPlugin.createAnnotationManager(AnnotationType.PointAnnotation, null);
//        }
//        // Set options for the resulting symbol layer.
//        PointAnnotationOptions pointAnnotationOptions = new PointAnnotationOptions()
//                .withPoint(Point.fromLngLat(longitude, latitude))
//                .withIconImage(BitmapUtil.getBitmapFromDrawable(mContext, drawable));
//        // Add the pointAnnotation to the map.
//        mPointAnnotationManager.create(pointAnnotationOptions);
    }

    /**
     * 在地图中添加View标记 [需补充代码后使用]
     * @param longitude 添加坐标
     * @param latitude  添加坐标
     * @param onClickListener   view点击回调
     */
    public void addViewAnnotationInMap(double longitude, double latitude, View.OnClickListener onClickListener) {
        if (mViewAnnotationManager == null) {
            mViewAnnotationManager = mMapView.getViewAnnotationManager();
        }
//        View markView = mViewAnnotationManager.addViewAnnotation(R.layout.item_map_image_view,    // view的layout id
//                new ViewAnnotationOptions.Builder()
//                        .geometry(Point.fromLngLat(longitude, latitude))
//                        .allowOverlap(true)   // 允许markView重叠
//                        .build());
        // 初始化 layout中的组件 markView.findViewById(R.id.xxx)
        // ...
    }

//    /**
//     * 向聚合层 添加 标记
//     * 添加操作会清空先前添加的标记
//     * @param photoAnnotationList   所有照片标记
//     */
//    public void setClusterLayerPhotoItem(List<PhotoAnnotation> photoAnnotationList) {
//        if (clusterLayer == null) {
//            return;
//        }
//        clusterLayer.setClusterMarkers(photoAnnotationList);
//    }
//
//    public void setClusterLayerClickListener(@Nullable ClusterLayer.OnClusterLayerClickListener clusterLayerClickListener) {
//        if (clusterLayer == null) {
//            return;
//        }
//        if (clusterLayerClickListener != null) {
//            // view点击事件获取是为了 判断 cluster中内容点击的，因此放在这里进行声明
//            ViewUtil.setOnViewClickPosListener(mContext, mMapView, onViewClickPosListener);
//            clusterLayer.setOnClusterClickListener(clusterLayerClickListener);
//        }
//    }
//
//    private final ViewUtil.OnViewClickPosListener onViewClickPosListener = new ViewUtil.OnViewClickPosListener() {
//        @Override
//        public void onClick(float clickX, float clickY) {
//            if (clusterLayer != null) {
//                clusterLayer.onMapClickEvent(clickX, clickY);
//            }
//        }
//    };
//
//    @SuppressLint("Lifecycle")
//    public void onDestroy() {
//        if (clusterLayer != null) {
//            clusterLayer.clearMarkersImageInStyle();
//        }
//        if (mLocationPlugin != null) {
//            mLocationPlugin.removeOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener);
//        }
//        if (mGesturesPlugin != null) {
//            mGesturesPlugin.removeOnMoveListener(onMoveListener);
//        }
//        if (mAnnotationPlugin != null && mPointAnnotationManager != null) {
//            mAnnotationPlugin.removeAnnotationManager(mPointAnnotationManager);
//        }
//        if (mMapView != null) {
//            mMapView.onDestroy();
//        }
//    }

    // 用户位置改变监听
    private final OnIndicatorPositionChangedListener onIndicatorPositionChangedListener =
            new OnIndicatorPositionChangedListener() {
                @Override
                public void onIndicatorPositionChanged(@NotNull Point point) {
                    mUserLocation = point;
                    if (!isCameraFollowUser && !isCameraToUserInit) {
                        isCameraToUserInit = true;
                        moveCameraTo(point, LOCATE_ZOOM_VALUE, 1500);
                    }
                    if (isCameraFollowUser && !isMapMoving && mMapView != null) {
                        // 相机跟随
                        moveCameraTo(point, LOCATE_ZOOM_VALUE, 0);
                        if (mGesturesPlugin != null){
                            mGesturesPlugin.setFocalPoint(mMapboxMap.pixelForCoordinate(point));
                        }
                    }
                }
    };

    // 地图移动监听
    private final OnMoveListener onMoveListener = new OnMoveListener() {
        @Override
        public void onMoveBegin(@NotNull MoveGestureDetector moveGestureDetector) {
            isMapMoving = true;
        }

        @Override
        public boolean onMove(@NotNull MoveGestureDetector moveGestureDetector) {
            return false;
        }

        @Override
        public void onMoveEnd(@NotNull MoveGestureDetector moveGestureDetector) {
            isMapMoving = false;
        }
    };

}
